import CodeBlock from "@theme/CodeBlock";

import Slices from "!!raw-loader!./14.slices.zig";
import Slices2 from "!!raw-loader!./14.slices-2.zig";

# Slices

Slices can be thought of many-item pointers (`[*]T`) with a length (`usize`).
These use the syntax `[]T`. Slices are easier to use safely and more convinient
than many-item pointers, as they store the valid length of the buffer with them.
Slices are sometimes referred to as "fat pointers" as they're typically double
the size of a normal pointer. Slices are the most common way to pass around
buffers in Zig.

:::go
Slicing in Zig is similar to slicing in Go, but you replace `array[start:end]`
with `array[start..end]`.

Moreover, in Go, there is no explicit ownership or memory management, meaning
that slices point to memory owned by the garbage collector. However in Zig,
slices point to manually-managed memory; slices are not tied to memory
allocation. This has important implications:

- The validity and lifetime of the backing memory is in the hands of the
  programmer.
- Zig slices do not have a Cap field, as they do not resize.

For a resizeable/appendable buffer with ownership, have a look at
[ArrayList](../02-standard-library/02-arraylist.mdx).

:::

Unlike many-item pointers, `for` loops work on slices.

The syntax `x[n..m]` is used to create a slice from an array, an operation known
as **slicing**. This creates a "slice" - a view into the array consisting of a
pointer and a length. Slicing includes the first element (`n`), but excludes the
last element (`m`).

In this example, a `const` slice is used in the `total` function as it doesn't
write to the slice's buffer.

<CodeBlock language="zig">{Slices}</CodeBlock>

When these `n` and `m` values are both known at compile time, slicing will
actually produce a pointer to an array. This is not an issue as a pointer to an
array i.e. `*[N]T` will coerce to a slice - `[]T`.

<CodeBlock language="zig">{Slices2}</CodeBlock>

The syntax `x[n..]` can also be used when you want to slice to the end.

```zig
test "slices 3" {
    var array = [_]u8{ 1, 2, 3, 4, 5 };
    var slice = array[0..];
    _ = slice;
}
```

Let's again compare our pointer types.

| Feature         | `*T`              | `*[N]T`            | `[*]T`                           | `[]T`               |
| --------------- | ----------------- | ------------------ | -------------------------------- | ------------------- |
| Dereferenceable | Yes, e.g. `ptr.*` | No                 | No                               | No                  |
| Indexable       | No                | Yes                | Yes                              | Yes                 |
| Sliceable       | No                | Yes                | Yes                              | Yes                 |
| Element Count   | Always 1          | Compile-time known | Unknown                          | Runtime known       |
| Arithmetic      | No                | No                 | Yes, e.g. `ptr + 1` or `ptr - 1` | No                  |
| Size            | @sizeOf(usize)    | @sizeOf(usize)     | @sizeOf(usize)                   | @sizeOf(usize) \* 2 |
| Attributes      | Yes               | Yes                | Yes                              | Yes                 |

:::info
We can now apply our knowledge and [make another program together](/posts/fahrenheit-to-celsius).

:::
